﻿// ==++==
// 
//   Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// ==--==
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.ExtendedReflection.ComponentModel;
using Microsoft.ExtendedReflection.Reasoning.ExecutionNodes;
using Microsoft.ExtendedReflection.Metadata;
using Microsoft.ExtendedReflection.Logging;
using Microsoft.ExtendedReflection.Collections;

namespace Microsoft.Pex.Fitness.Interfaces
{
    /// <summary>
    /// This interface defines a service at the exploration level,
    /// that both the fitness search frontier and the
    /// fitness path monitor use.
    /// </summary>
    internal interface IPexFitnessExplorationManager :
        IService
    {
        int GetComputedFitness(IExecutionNode node);
        IFiniteMap<int, PexCompositeFitnessValue> GetTargetFitnessInfo(IExecutionNode node);
        string GetCompositeFitnessRepresentation(IExecutionNode node);
        void SetUserPriority(MethodDefinition method, int preference);

        int GetTargetHash(ICallStackTrace callStackTrace, MethodDefinition method, int programCounter, bool taken);
        IFiniteSet<MethodDefinition> GetMethodsOfTargetHash(int targetID);
        
        bool HasCoveredTarget(int targetID);
        void AddCoveredTarget(int targetID);
        void SendEventOnTargetCoverage(IExecutionNode flippedNode, int targetID);

        void SetCoveredTarget(IExecutionNode flippedNode, int targetID);
        
        void RemoveFitnessAfterTargetCoverage(int targetID);
        void RemoveFitnessGainAfterTargetCoverage(int branchID);
        bool SetFitnessValueToNode(
            SafeSet<int> targetsImprovedInThisPath, 
            IExecutionNode flippedNode, 
            IExecutionNode node, 
            int targetID, int pathFitnessValue, int targetFitnessGain, int branchID);
        
        bool IsReachedNonBooleanComparison(MethodDefinition method, int programCounter);
        void ReachedNonBooleanComparison(MethodDefinition method, int programCounter);

        void SetFitness(
            SafeSet<int> targetsImprovedInThisPath,
            IExecutionNode flippedNode, 
            IEnumerable<IExecutionNode> reversePath,
            int targetID, int pathFitnessValue);

        event RemoteEventHandler<PexFitnessEventArgs> OnFitness;
        event RemoteEventHandler<PexFitnessEventArgs> OnTargetCoverage;
        event RemoteEventHandler<PexFitnessEventArgs> OnTargetFitnessImprovement;

        bool TryGetUserPriority(MethodDefinition method, out int priority);

        bool IsLoggingVerboseEnabled { get; }
        bool IsLoggingEnabled { get; }
        bool UseBranchFitnessGain { get; }

#if DEBUG
        void SetSelectedFrontierInfo(int targetID, int fitnessValue, int priority);
        string GetTargetIDString(int target);
        string GetBranchIDString(int branch);
        string GetIDMapString();
        SafeIntDictionary<string> TargetIDMap { get; }
        int CurrentPathNumber { get; }
        void NextPathNumber();
#endif
    }
}
